package com.apes.scm.masterdata.product.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.DefaultPersistListener;
import com.apes.framework.jpa.Model;
import com.apes.framework.jpa.comment.Comment;
import com.apes.framework.jpa.generator.ApesGenerator;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.scm.masterdata.product.model.*;
import com.apes.scm.masterdata.product.repository.ProductNegativeSellingRepository;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.SelectBeforeUpdate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import javax.persistence.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: apes-server
 * @description:
 * @author: czs
 * @create: 2023-02-03 15:24
 **/
@Service("productNegativeSellingService")
public class ProductNegativeSellingService extends DomainService {


    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private ProductNegativeSellingRepository productNegativeSellingRepository;

    private Map create(SimpleRequest request){
        JSONObject jo = request.getJO();
        JSONArray productItem = jo.getJSONArray("productItem");
        List result = new ArrayList();
        for (Object o : productItem) {
            if (o instanceof JSONObject){
                JSONObject jsonObject = (JSONObject) o;
                JSONObject product1 = jsonObject.getJSONObject("product1");
                String id = product1.getString("id");
                Product product = productRepository.findOne(id);
                ProductNegativeSelling negativeSelling = productCreate(product);
                result.add(negativeSelling);
            }
        }

        return mapper("total",result.size(),"page",0,"pages",1,"content",mapper("productItem",result));
    }

    private ProductNegativeSelling productCreate(Product product) {
        ProductNegativeSelling negativeSelling = new ProductNegativeSelling();
        negativeSelling.setProduct(product);
        save(negativeSelling);
        return negativeSelling;
    }

    private void save(ProductNegativeSelling negativeSelling) {
        try {
            productNegativeSellingRepository.saveAndFlush(negativeSelling);
        } catch (Exception e) {
            String message = e.getMessage();
            boolean contains = message.contains("ORA-00001");
            if (contains)message="请勿重复定义商品:"+negativeSelling.getProduct().getId();
            throw new RuntimeException(message);

        }
    }

    private JSONObject importData(SimpleRequest request){
        JSONObject jo = request.getJO();
        JSONArray data = jo.getJSONArray("data");
        List<String> name = data.stream().map(o -> ((JSONObject) o).getString("name")).collect(Collectors.toList());
        JSONObject sheet = jo.getJSONObject("importData");
        JSONObject result = new JSONObject();
        Iterator<String> iterator = sheet.keySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            JSONArray jsonArray = sheet.getJSONArray(key);
            if (jsonArray.isEmpty())continue;
            List sheetData = new ArrayList();
            sheetData.add(name);
            JSONArray rowTitle = (JSONArray) jsonArray.get(0);
            //获取有用的商品编码列
            int targetRow = -1;
            for (int i = 0; i < rowTitle.size(); i++) {
                String title = (String) rowTitle.get(i);
                if (title.equals("ID")||title.contains("商品编码"))targetRow = i;
            }


            if (targetRow<0)continue;
            List<ProductNegativeSelling> productNegativeSellings = new ArrayList<>();
            //根据获取到的列取列数据
            List<String> productIds = new ArrayList<>();
            for (int i = 1; i < jsonArray.size(); i++) {
                JSONArray rowContent = (JSONArray) jsonArray.get(i);
                String productId = (String) rowContent.get(targetRow);
                if (productId==null)continue;
                productIds.add(productId);
                //每500行数据分阶段保存
                if (productIds.size()>500){
                    productNegativeSellings = idCreateProductNegativeSelling(productIds);
                    productIds = new ArrayList<>();
                }
            }
            if (productIds.size()>0){
                productNegativeSellings = idCreateProductNegativeSelling(productIds);
                productIds = new ArrayList<>();
            }
            int size = productNegativeSellings.size();
            if (size<50) size+=50;
            for (int i = size-51; i > 0; i--) {
                ProductNegativeSelling productNegativeSelling = productNegativeSellings.get(i);
                Product product = productNegativeSelling.getProduct();
                JSONArray row = new JSONArray();
                row.add(i);
                row.add("0");
                row.add(product.getId());
                row.add(product.getName());
                row.add(product.getBrand().getName());
                row.add(product.getCategory().getName());
                row.add(product.getClassify().getName());
                row.add(getProductState(product.getState()));
                row.add(productNegativeSelling.getId());
                sheetData.add(row);
            }

            result.put(key,sheetData);
        }
        if (result.isEmpty())throw new RuntimeException("在表种第一行找不到商品编码列.请重新检查数据");

        return result;
    }
    private List<ProductNegativeSelling> idCreateProductNegativeSelling(List<String> ids){
        //检查数据
        List<Product> product = productRepository.findAll(JpaDsl.toCriteria("id","IN",ids));
        if (product.size()!=ids.size()){
            product.forEach(product1 -> {
                if (!ids.contains(product1.getId()))throw new RuntimeException("商品不存在:"+product1.getId());
            });
        }
        List<ProductNegativeSelling> all = productNegativeSellingRepository.findAll(JpaDsl.toCriteria("product.id", "IN", ids));
        if (!all.isEmpty())throw new RuntimeException("重复的商品:"+all.stream().findFirst().get().getProduct().getId());
        //创建
        List<ProductNegativeSelling> productNegativeSellings = new ArrayList<>();
        for (Product product1 : product) {
            ProductNegativeSelling negativeSelling = new ProductNegativeSelling();
            negativeSelling.setProduct(product1);
            productNegativeSellings.add(negativeSelling);
        }

        return productNegativeSellingRepository.saveAll(productNegativeSellings);
    }
    private Object deleteData(SimpleRequest request){
        JSONArray jo = request.getJA();
        List<String> ids = new ArrayList<>();
        for (Object o : jo) {
            JSONObject jsonObject = (JSONObject) o;
            ids.add(jsonObject.getString("id"));
        }
        if (ids.isEmpty())throw new RuntimeException("请至少勾选一个商品");
        productNegativeSellingRepository.deleteAll(productNegativeSellingRepository.findAll(JpaDsl.toCriteria("id","IN",ids)));
        return null;
    }
    private Object findAllData(SimpleRequest request){
        JSONObject jo = request.getJO();
        Integer page = jo.get("page")==null?0: getInt(jo,"page");
        Integer size = jo.get("size")==null?50:getInt(jo,"size");
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        List condition = new ArrayList();
        getCondition("product.brand.id","EQ",jo.getString("PP")==null?null:jo.getJSONObject("PP").getString("id"), condition);
        getCondition("product.state","EQ",jo.getString("SPZT"), condition);
        getCondition("product.classify.id","like",jo.getString("classify"), condition);
        getCondition("product.id","EQ",jo.getJSONObject("product1")==null?null:jo.getJSONObject("product1").getString("id"), condition);
        getCondition("product.category.id","EQ",jo.getString("categoryTemp")==null?null:jo.getJSONObject("categoryTemp").getString("id"), condition);
        Page<ProductNegativeSelling> negativeSellingPage = productNegativeSellingRepository.findAll(JpaDsl.toCriteria(condition), PageRequest.of(page, size, sort));

        List<Map> result = returnToWeb(negativeSellingPage);

        return new PageImpl(result, negativeSellingPage.getPageable(), negativeSellingPage.getTotalElements());
    }
    private Object exportData(SimpleRequest request){
        JSONObject jo = request.getJO().getJSONObject("condition");
        List condition = new ArrayList();
        getCondition("product.brand.id","EQ",jo.getString("PP")==null?null:jo.getJSONObject("PP").getString("id"), condition);
        getCondition("product.state","EQ",jo.getString("SPZT"), condition);
        getCondition("product.classify.id","like",jo.getString("classify"), condition);
        getCondition("product.id","EQ",jo.getJSONObject("product1")==null?null:jo.getJSONObject("product1").getString("id"), condition);
        getCondition("product.category.id","EQ",jo.getString("categoryTemp")==null?null:jo.getJSONObject("categoryTemp").getString("id"), condition);
        Page<ProductNegativeSelling> negativeSellingPage = productNegativeSellingRepository.findAll(JpaDsl.toCriteria(condition), PageRequest.of(0, 99999));

        List<Map> result = returnToWeb(negativeSellingPage);

        return new PageImpl(result, negativeSellingPage.getPageable(), negativeSellingPage.getTotalElements());
    }

    private List<Map> returnToWeb(Page<ProductNegativeSelling> negativeSellingPage) {
        return negativeSellingPage.getContent().stream().map(productNegativeSelling -> {
                Product product = productNegativeSelling.getProduct();
                Brand brand = product.getBrand();
                if (brand==null)return mapper("productId", product.getId(), "productName", product.getName());
                Category category = product.getCategory();
                if (category==null)return mapper("productId", product.getId(), "productName", product.getName());
                Classify classify = product.getClassify();
                if (classify==null)return mapper("productId", product.getId(), "productName", product.getName());
                return mapper("productId", product.getId(), "productName", product.getName(),
                        "id",productNegativeSelling.getId(),
                        "brandName", brand.getName(), "categoryName", category.getName(),
                        "classifyName", classify.getName(), "state", getProductState(product.getState()));
            }).collect(Collectors.toList());
    }

    private int getInt(JSONObject jo,String name) {
        Object o = jo.get(name);
        if (o.equals(""))return 0;
        if (o instanceof String)return Integer.parseInt((String) o);
        if (o instanceof Integer)return (Integer) o;
        return 0;
    }

    private void getCondition(String filed,String op,String key, List condition) {
        if (key!=null){
            Map map = new HashMap();
            map.put("field",filed);
            map.put("value",key);
            map.put("operator",op);
            map.put("type","string");
            condition.add(map);
        }
    }

    /**
     * 判断商品是否可负卖
     * @param productId
     * @return true 可负卖  false 非可负卖
     */
    public boolean isProductNegativeSelling(String productId){
        List<ProductNegativeSelling> productNegativeSellings = productNegativeSellingRepository.findAll(JpaDsl.toCriteriaByEq("product.id", productId));
        return productNegativeSellings.size() > 0 ? true : false;
    }

    private String getProductState(String state){
        //0:正常 2：停产下市 3.停用 5：预上市
        switch (state){
            case "0":
                return "正常";
            case "2":
                return "停产下市";
            case "3":
                return "停用";
            case "5":
                return "预上市";
                default:
                    return state;
        }
    }
}
